///////////////////////////////////////////////////////////////////////////////
// Constants
///////////////////////////////////////////////////////////////////////////////

// We would prefer having only a single z-index for all overlay modes,
// possibly controlled by a single, shared CSS variable.
// However, there is an issue when a layer has a fixed navigation bar:
//
// - If the bar's z-index is lower than the one from Unpoly's layers,
//   popups from the underlying page will overlap the bar
// - If the bar's z-index is higher than the one from Unpoly's layers,
//   a drawer or modal will no longer overlap the fixed bar
//
// Hence we have two z-indexes. A fixed navigation bar needs to have a z-index
// between those two. The default z-index for a fixed Bootstrap 4 navigation bar
// (.navbar.fixed-top) is 1030.
$overlay-with-tether-z-index: 1000
$overlay-with-viewport-z-index: 2000

:root
  // Currently all overlay modes with a viewport have the same backdrop.
  // When we do a lightbox mode, we will need a darker backdrop for that one mode.
  // Hence we cannot share it across all modes using a CSS variable.
  --up-overlay-backdrop: rgba(0, 0, 0, 0.4)

  // If multiple modals are nested inside each other, the padding is
  // multiplied by the nesting depth.
  --up-modal-viewport-padding-x: 15px
  --up-modal-viewport-padding-y: 25px

up-focus-trap
  // Prevent focusing the trap from scrolling the underlying root layer
  position: fixed
  top: 0
  left: 0
  width: 0
  height: 0

///////////////////////////////////////////////////////////////////////////////
// Virtual %elements shared by multiple overlay modes
///////////////////////////////////////////////////////////////////////////////

%maximize
  top: 0
  left: 0
  bottom: 0
  right: 0

%large-shadow
  box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.3)

%small-shadow
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.3)

%no-focus-outline
  &:focus,
  &:focus-visible
    outline: none

%overlay-with-viewport
  @extend %maximize
  @extend %no-focus-outline
  // Create a stacking context for child elements by giving a position and z-index.
  // This way the z-indexes of our child elements don't need to be defined.
  z-index: $overlay-with-viewport-z-index
  position: fixed

%overlay-backdrop
  @extend %maximize
  position: absolute
  background: var(--up-overlay-backdrop)

%overlay-viewport
  @extend %maximize
  position: absolute

  // The viewport always has a scrollbar, except when we're animating (see below)
  overflow-y: scroll
  overflow-x: hidden

  // Prevent users from scrolling a parent layer when they bump
  // into the end of this layer's viewport.
  overscroll-behavior: contain

  display: flex
  align-items: flex-start

  // Center %up-overlay-box within the viewport.
  // This also turns block children into flex children, so they can grow with content,
  // up to our max-width of 100%.
  justify-content: center

%overlay-box
  // We focus the box after the overlay was opened.
  @extend %no-focus-outline

  position: relative

  // Include the padding in any width that might be set on the frame
  box-sizing: border-box

  // Regardless of size we never want to grow wider than the viewport,
  // which would cause horizontal scroll bars.
  max-width: 100%

  background-color: #fff
  padding: 20px

  overflow-x: hidden

%overlay-content
  // Custom elements are display: inline by default, which is not a good container
  // for content. It will cause children not to take up availabile space.
  // We can make %overlay-content display: block without it taking up 100% width
  // because our container %overlay-box is already display: inline-block, limiting
  // children to their intrinsic width.
  display: block

%overlay-with-tether
  z-index: $overlay-with-tether-z-index

%overlay-dismiss
  color: #888
  position: absolute
  top: 10px
  right: 10px
  font-size: 1.7rem
  // This line-height will position a sans-serif "×" with equal distance to the
  // top and right border, even when the font-size changes.
  line-height: 0.5
  cursor: pointer


///////////////////////////////////////////////////////////////////////////////
// Modals are a centered window with its own scrollbar
///////////////////////////////////////////////////////////////////////////////
up-modal
  @extend %overlay-with-viewport

up-modal-backdrop
  @extend %overlay-backdrop

up-modal-viewport
  @extend %overlay-viewport

  // Implement the margin around the dialog box with a padding of the viewport.
  // This way we can give .up-overlay-box a max-width of 100%, (1) preventing people
  // from setting withs larger than the viewport, and (2) sizing approproately
  // if the modal contents are very wide and cannot wrap (e.g. code blocks).
  @for $nesting from 0 through 4
    up-modal[nesting="#{$nesting}"] &
      padding-inline: calc(#{$nesting + 1} * var(--up-modal-viewport-padding-x))
      padding-block: calc(#{$nesting + 1} * var(--up-modal-viewport-padding-y))

up-modal-box
  @extend %overlay-box
  @extend %large-shadow

  up-modal[size=small] &
    width: 350px

  up-modal[size=medium] &
    width: 650px

  up-modal[size=large] &
    width: 1000px

  up-modal[size=grow] &
    width: auto // This is also the default value, but be explicit

  up-modal[size=full] &
    width: 100%

up-modal-content
  @extend %overlay-content

up-modal-dismiss
  @extend %overlay-dismiss


///////////////////////////////////////////////////////////////////////////////
// Drawers are a full-height modal clinging to the left or right edge of the screen
///////////////////////////////////////////////////////////////////////////////
up-drawer
  @extend %overlay-with-viewport

up-drawer-backdrop
  @extend %overlay-backdrop

up-drawer-viewport
  @extend %overlay-viewport

  // Allow frame to grow from the left, up to its max-width of 100%
  justify-content: flex-start

  up-drawer[position=right] &
    // Allow frame to grow from the right, up to its max-width of 100%
    justify-content: flex-end

up-drawer-box
  @extend %overlay-box
  @extend %large-shadow
  min-height: 100vh

  up-drawer[size=small] &
    width: 150px

  up-drawer[size=medium] &
    width: 340px

  up-drawer[size=large] &
    width: 600px

  up-drawer[size=grow] &
    width: auto // This is also the default value, but be explicit

  up-drawer[size=full] &
    width: 100%

up-drawer-content
  @extend %overlay-content

up-drawer-dismiss
  @extend %overlay-dismiss


///////////////////////////////////////////////////////////////////////////////
// Cover is an overlay that fills the entire screen
///////////////////////////////////////////////////////////////////////////////
up-cover
  @extend %overlay-with-viewport

up-cover-viewport
  @extend %overlay-viewport

up-cover-box
  @extend %overlay-box
  width: 100%
  min-height: 100vh

  // We assume the developer wants to embed a full application layout
  // into a cover overlay. That layout will either want to touch the screen
  // edges, so we remove all padding.
  padding: 0

up-cover-content
  @extend %overlay-content

up-cover-dismiss
  @extend %overlay-dismiss


///////////////////////////////////////////////////////////////////////////////
// Popup is a small box that is anchored to a link
///////////////////////////////////////////////////////////////////////////////
up-popup
  @extend %overlay-with-tether
  @extend %overlay-box
  @extend %small-shadow

  // The small popup box looks better with a tighter padding.
  padding: 15px

  // position: absolute is given by up.Tether

  &[size=small]
    width: 180px

  &[size=medium]
    width: 300px

  &[size=large]
    width: 550px

  &[size=grow] &
    width: auto // This is also the default value, but be explicit

  &[size=full] &
    width: 100%

  // The up-popup[align=right] attribute right-aligns the text because HTML.
  // We reset the text alignment to left.
  text-align: left

up-popup-content
  @extend %overlay-content

up-popup-dismiss
  @extend %overlay-dismiss
